#ifndef _MY_STACK_TCC
#define _MY_STACK_TCC

#include <iostream>

template<typename T>
void my_stack<T>::push(const T& data) {
	node<T>* const newNode = new node<T>(data);
	newNode->next = head.load();
	while (!head.compare_exchange_weak(newNode->next, newNode));
}

template<typename T>
shared_ptr<T> my_stack<T>::pop() {
	atomic<void*>& hp = getHazardPointerForCurrentThread();
	node<T>* oldHead = head.load();
	do {
		node<T>* temp;
		do {
			temp = oldHead;
			hp.store(oldHead);
			oldHead = head.load();
		} while (temp != oldHead);
	} while (oldHead && !head.compare_exchange_weak(oldHead, oldHead->next));
	// continuer ici
}

template<typename T>
void my_stack<T>::addToReclaim(dataToReclaim* n) {
	n->next = nodesToReclaim.load();
	while (!nodesToReclaim.compare_exchange_weak(n->next, n));
}

template<typename T>
void my_stack<T>::reclaimLater(T* data) {
	addToReclaim(new dataToReclaim(data));
}

template<typename T>
void my_stack<T>::deleteNodesWithNoHazards() {
	dataToReclaim* const current = nodesToReclaim.exchange(nullptr);
	while (current) {
		dataToReclaim* const next = current->next;
		if (!outstandingHazardPointersFor(current->data)) {
			delete current;
		} else {
			reclaimLater(current);
		}
		current = next;
	}
}

template<typename T>
atomic<void*>& my_stack<T>::getHazardPointerForCurrentThread() {
	static __thread hp_owner h;
	return h.getPointer();
}

template<typename T>
bool my_stack<T>::outstandingHazardPointersFor(void* p) {
	for (int i = 0; i < MAX_HAZARD_PTR; i++) {
		if (hp_owner::ptrs[i].ptr.load() == p) {
			return true;
		}
	}
	return false;
}

template<typename T>
void my_stack<T>::afficher() const {
	node<T>* current = head.load();
	while (current) {
		cout << *current->data << " ";
		current = current->next;
	}
	cout << endl;
}

template<typename T>
my_stack<T>::~my_stack() {
}

#endif
